﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace Kimd.Vision
{
	public partial class DrawingBoard : UserControl
	{
		#region delegate
		public delegate void ShapeDelegate(ShapeNB shape, int val);
		#endregion

		#region const
		public const int EVENT_UPDATE_ROI = 50;
		public const int EVENT_DELETED_ACTROI = 53;
		public const int EVENT_DELETED_ALL_ROIS = 54;
		public const int EVENT_ACTIVATED_ROI = 55;
		public const int EVENT_CREATED_ROI = 56;
        public const int EVENT_FINISHEDIT_ROI = 57;
        public const string GC_COLOR = "Color";
		public const string GC_COLORED = "Colored";
		public const string GC_LINEWIDTH = "LineWidth";
		public const string GC_DRAWMODE = "DrawMode";
		#endregion

		#region Property
		/// <summary>
		/// 原始图片宽度
		/// </summary>
		private int _imageWidth = 1280;
		public int ImageWidth
		{
			get { return _imageWidth; }
			private set
			{
				if (_imageWidth != value)
				{
					if (NotifyImageSize != null)
						NotifyImageSize(string.Format("{0} x {1}", value.ToString().PadLeft(4), _imageHeight.ToString().PadLeft(4)));
				}
				_imageWidth = value;
			}
		}
		/// <summary>
		/// 原始图片高度
		/// </summary>
		private int _imageHeight = 960;
		public int ImageHeight
		{
			get { return _imageHeight; }
			private set
			{
				if (_imageHeight != value)
				{
					if (NotifyImageSize != null)
                        NotifyImageSize(string.Format("{0} x {1}", _imageWidth.ToString().PadLeft(4), value.ToString().PadLeft(4)));
				}
				_imageHeight = value;
			}
		}
		/// <summary>
		/// 原图上截取部分的高度
		/// </summary>
		private float _drawHeight;
		/// <summary>
		/// 原图上截取部分的宽度
		/// </summary>
		private float _drawWidth;
		/// <summary>
		/// 显示区宽度
		/// </summary>
		private int DisplayWidth
		{
			get { return this.hWC_Displayer.Width; }
		}
		/// <summary>
		/// 显示区高度
		/// </summary>
		private int DisplayHeight
		{
			get { return this.hWC_Displayer.Height; }
		}
		/// <summary>
		/// 开始拖拽动作
		/// </summary>
		private bool _startDrag;
		/// <summary>
		/// 拖拽移动图片起始点
		/// </summary>
		private PointF _dragStartPoint;
		/// <summary>
		/// 图片缩放不动点
		/// </summary>
		private PointF _zoomPoint;
        public bool IsShowOnly;
		/// <summary>
		/// 显示图片
		/// </summary>
        /// 
		private HObject _originalImage;
		public HObject OriginalImage
		{
			get
			{
				return _originalImage;
			}
			set
			{
                lock (this)
                {
                    if (value == null)
                        return;
                    if (!value.IsInitialized())
                        return;
                    if (_originalImage != null)
                        _originalImage.Dispose();
                    _originalImage = value;
                    HTuple h, w;
                    HOperatorSet.GetImageSize(value, out w, out h);
					if (w.I != ImageWidth || h.I != ImageHeight)
                    {
                        ImageWidth = w.I;
                        ImageHeight = h.I;
                        showImageSize();
						resizeDrawingArea();
						computeDrawingArea();
						updateCrossLine();
                        Fit2Screen();
                    }
                    else
					{
						Repaint(); 
                    }
                }
			}
		}
		/// <summary>
		/// 比例缩放因子
		/// </summary>
		private double _zoomFactor = 1;
		public double ZoomFactor
		{
			get { return _zoomFactor; }
			set
			{
				_zoomFactor = value;
				if (_originalImage != null)
				{
					if (_zoomFactor > 15) _zoomFactor = 15;
					if (_zoomFactor < 0.05) _zoomFactor = 0.05;
					if (_zoomFactor < Math.Min(DisplayWidth * 1.0 / _imageWidth, DisplayHeight * 1.0 / _imageHeight))
						_zoomFactor = Math.Min(DisplayWidth * 1.0 / _imageWidth, DisplayHeight * 1.0 / _imageHeight);
					if (_originalImage != null)
						computeDrawingArea();
				}
                Repaint();
			}
		}
		/// <summary>
		/// 图片起始X位置
		/// </summary>
		private float _originX;
		public float OriginX
		{
			get { return _originX; }
			set
			{
				_originX = value;
				if (_originalImage != null)
				{
					_originX = _originX > _imageWidth - (DisplayWidth / _zoomFactor) ? (float)(_imageWidth - (DisplayWidth / _zoomFactor)) : _originX;
					_originX = _originX < 0 ? 0 : _originX;
				}
			}
		}
		/// <summary>
		/// 图片起始Y位置
		/// </summary>
		private float _originY;
		public float OriginY
		{
			get { return _originY; }
			set
			{
				_originY = value;
				if (_originalImage != null)
				{
					_originY = _originY > _imageHeight - (DisplayHeight / _zoomFactor) ? (float)(_imageHeight - (DisplayHeight / _zoomFactor)) : _originY;
					_originY = _originY < 0 ? 0 : _originY;
				}
			}
		}
		/// <summary>
		/// 背景色
		/// </summary>
		private Color _displayerBackColor;
		public Color DisplayerBackColor
		{
			set
			{
				hWC_Displayer.BackColor = value;
				_displayerBackColor = value;
			}
		}
		public ShapeDelegate NotifyObserver;
		public Action<string> NotifyGrayVal;
		public Action<string> NotifyImageSize;
		private bool _drawRectangle1;
		private bool _drawCircle;
		private bool _drawRectangle2;
		private bool _drawPolygon;
		private bool _drawSector;
        private bool _drawPoint;
        /// <summary>
        /// 所有绘制的图形
        /// </summary>
        public List<ShapeNB> CreatedShapes;
		public List<DisplayHObjectNB> CreatedRegions;
		private string _description;
		public string Description
		{
			get
			{
				return _description;
			}
			set
			{
				_description = value;
				this.l_Description.Text = value;
			}
		}
		private bool _isShowDescription;
		public bool IsShowDescription
		{
			set
			{
                if (l_Description.InvokeRequired)
                {
                    this.Invoke(new Action(() =>
                    {
                        _isShowDescription = value;
                        l_Description.Visible = _isShowDescription;
                        l_Info.Visible = _isShowDescription;
                    }));
                }
                else
                {
                    _isShowDescription = value;
                    l_Description.Visible = _isShowDescription;
                    l_Info.Visible = _isShowDescription;
                }
            }

		}
		public Action<int> DisplayerMaximize;
		public Action<int> DisplayerSelected;
        public Action GetFocus;
        private Dictionary<string, object> currentGraphicsContext;
		public bool DisableEdit;
        public bool IsShowCross = false;
        private HObject hLine;
        private HObject vLine;
        public bool IsShowMarkRect;
        public Rectangle1NB MarkCenterRect;
		public Action OnLeftMouseDoubleClick;
		public bool ChangeSize;
        public bool IsAllowMouse { get; set; }
        #endregion

        #region Constructor
        public DrawingBoard()
		{
			InitializeComponent();
			this.CreatedShapes = new List<ShapeNB>();
			this.CreatedRegions = new List<DisplayHObjectNB>();
			currentGraphicsContext = new Dictionary<string, object>();
			currentGraphicsContext.Add(GC_COLOR, "black");
			currentGraphicsContext.Add(GC_DRAWMODE, "fill");
			currentGraphicsContext.Add(GC_LINEWIDTH, 100);
            currentGraphicsContext.Add(GC_COLORED, 0);
        }
		#endregion

		#region Method
		/// <summary>
		/// 根据缩放比计算图片截取宽高
		/// </summary>
		private void computeDrawingArea()
		{
			_drawHeight = (int)(DisplayHeight / _zoomFactor);
			_drawWidth = (int)(DisplayWidth / _zoomFactor);
        }
        /// <summary>
        /// 重定义hwindowcontrol的大小，是图像居中
        /// </summary>
        private void resizeDrawingArea()
        {
            double factor = 0;
            if (this.Width * 1.0 / this.Height > _imageWidth * 1.0 / _imageHeight)
            {
                factor = _imageWidth * 1.0 / _imageHeight;
                this.Invoke(new Action(() =>
                {
                    hWC_Displayer.Size = new Size((int)(this.Height * factor), this.Height);
                    hWC_Displayer.Location = new Point((this.Width - (int)(this.Height * factor)) / 2, 0);
                    l_Description.Location = new Point((this.Width - (int)(this.Height * factor)) / 2, 0);
                    l_Info.Location = new Point((this.Width - (int)(this.Height * factor)) / 2, l_Description.Height);
					l_RunInfo.Location = new Point((this.Width - (int)(this.Height * factor)) / 2, this.Height - l_RunInfo.Height);
				}));
			}
            else
            {
                factor = _imageHeight * 1.0 / _imageWidth;
                this.Invoke(new Action(() =>
                {
                    hWC_Displayer.Size = new Size(this.Width, (int)(this.Width * factor));
                    hWC_Displayer.Location = new Point(0, (this.Height - (int)(this.Width * factor)) / 2);
                    l_Description.Location = new Point(0, (this.Height - (int)(this.Width * factor)) / 2);
                    l_Info.Location = new Point(0, (this.Height - (int)(this.Width * factor)) / 2 + l_Description.Height);
					l_RunInfo.Location = new Point(0, (this.Height - (int)(this.Width * factor)) / 2 + (int)(this.Width * factor) - l_RunInfo.Height);
				}));
            }
        }
        /// <summary>
        /// 显示图片宽高
        /// </summary>
        private void showImageSize()
		{
			if (_imageWidth == 0 || _imageHeight == 0)
				return;
			//this.tSSL_Size.Text = string.Format("{0}×{1}", _imageWidth, _imageHeight);
		}
        public void updateCrossLine()
        {
            HOperatorSet.GenRegionLine(out hLine, _imageHeight / 2, 0, _imageHeight / 2, _imageWidth);
            HOperatorSet.GenRegionLine(out vLine, 0, _imageWidth / 2, _imageHeight, _imageWidth / 2);
        }
		/// <summary>
		/// 图片放大缩小
		/// </summary>
		/// <param name="inorout">true时放大,false时缩小</param>
		public void ZoomImage(bool inorout)
		{
			double zoomFactorNow = 0;
			double zoomFactorBefore = ZoomFactor;  //前次的放大因子
			zoomFactorNow = inorout ? Math.Round(ZoomFactor * 1.08, 3) : Math.Round(ZoomFactor * 0.92, 3);
			OriginX = OriginX + (float)(_zoomPoint.X * (1 / zoomFactorBefore - 1 / zoomFactorNow));
			OriginY = OriginY + (float)(_zoomPoint.Y * (1 / zoomFactorBefore - 1 / zoomFactorNow));
			ZoomFactor = zoomFactorNow;
		}
		/// <summary>
		/// 图片移动
		/// </summary>
		/// <param name="currentPoint">图片拖拽点</param>
		private void moveImage(PointF currentPoint)
		{
			float dragOffsetX = currentPoint.X - _dragStartPoint.X;
			float dragOffsetY = currentPoint.Y - _dragStartPoint.Y;
			OriginX = OriginX - dragOffsetX;
            OriginY = OriginY - dragOffsetY;
            //Console.WriteLine(DateTime.Now.ToString("fff: repaint2"));
			Repaint();
		}
		/// <summary>
		/// 窗口点转换为图片点
		/// </summary>
		/// <param name="p"></param>
		/// <returns></returns>
		private PointF windowPixel2Image(PointF p)
		{
			return new PointF((float)(p.X / _zoomFactor + _originX), (float)(p.Y / _zoomFactor + _originY));
		}
		/// <summary>
		/// 图片点转换为窗口点
		/// </summary>
		/// <param name="p"></param>
		/// <returns></returns>
		private PointF imagePixel2Window(PointF p)
		{
			return new PointF((float)((p.X - _originX) * _zoomFactor), (float)((p.Y - _originY) * _zoomFactor));
		}
		/// <summary>
		/// 窗口长度转为图片长度
		/// </summary>
		/// <param name="len"></param>
		/// <returns></returns>
		private float windowLen2Image(float len)
		{
			return (float)(len / _zoomFactor);
		}
		/// <summary>
		/// 图片长度转为窗口长度
		/// </summary>
		/// <param name="len"></param>
		/// <returns></returns>
		private float imageLen2Window(float len)
		{
			return (float)(len * _zoomFactor);
		}
		private void changeGraphicsContext(Dictionary<string, object> context)
		{
			foreach (KeyValuePair<string, object> kvp in context)
			{
				switch (kvp.Key)
				{
					case GC_COLOR:
                        if ((string)currentGraphicsContext[GC_COLOR] != (string)context[GC_COLOR])
                        {
							hWC_Displayer.HalconWindow.SetColor((string)kvp.Value);
                            currentGraphicsContext[GC_COLOR] = context[GC_COLOR];
                        }
						break;
					case GC_DRAWMODE:
                        if ((string)currentGraphicsContext[GC_DRAWMODE] != (string)context[GC_DRAWMODE])
						{
							hWC_Displayer.HalconWindow.SetDraw((string)kvp.Value);
                            currentGraphicsContext[GC_DRAWMODE] = context[GC_DRAWMODE];
                        }
						break;
					case GC_LINEWIDTH:
						if ((int)currentGraphicsContext[GC_LINEWIDTH] != (int)context[GC_LINEWIDTH])
						{
							hWC_Displayer.HalconWindow.SetLineWidth(Convert.ToInt32(kvp.Value));
                            currentGraphicsContext[GC_LINEWIDTH] = context[GC_LINEWIDTH];
                        }
						break;
					case GC_COLORED:
                        if ((string)currentGraphicsContext[GC_COLORED] != (string)context[GC_COLORED])
						{
							hWC_Displayer.HalconWindow.SetColored(Convert.ToInt32(kvp.Value));
                            currentGraphicsContext[GC_COLORED] = context[GC_COLORED];
                        }
						break;
					default:
						break;
				}
			}
		}
		/// <summary>
		/// 重绘显示
		/// </summary>
		public void Repaint()
		{
            lock (this)
            {
                try
                {
                    System.Drawing.Rectangle rect = hWC_Displayer.ImagePart;
                    rect.X = (int)_originX;
                    rect.Y = (int)_originY;
                    rect.Height = (int)_drawHeight;
                    rect.Width = (int)_drawWidth;
                    hWC_Displayer.ImagePart = rect;

                    HSystem.SetSystem("flush_graphic", "false");
                    hWC_Displayer.HalconWindow.ClearWindow();
                    if (_originalImage != null && _originalImage.IsInitialized())
                    {
                        hWC_Displayer.HalconWindow.DispObj(_originalImage);
                        if (IsShowCross)
                        {
                            if (hLine != null && vLine != null)
                            {
                                hWC_Displayer.HalconWindow.SetLineWidth(1);
                                hWC_Displayer.HalconWindow.SetColor("#23ac44");
								currentGraphicsContext[GC_LINEWIDTH] = 1;
								currentGraphicsContext[GC_COLOR] = "#23ac44";
								hWC_Displayer.HalconWindow.DispObj(hLine);
                                hWC_Displayer.HalconWindow.DispObj(vLine);
                            }
                        }
                        if (IsShowMarkRect && MarkCenterRect != null)
                        {
                            try
                            {
                                hWC_Displayer.HalconWindow.SetLineWidth(1);
                                hWC_Displayer.HalconWindow.SetColor("#f5ea1a");
                                hWC_Displayer.HalconWindow.SetDraw("margin");
								currentGraphicsContext[GC_LINEWIDTH] = 1;
								currentGraphicsContext[GC_COLOR] = "#f5ea1a";
								currentGraphicsContext[GC_DRAWMODE] = "margin";
								//if (hLine != null && vLine != null)
								{
                                    hWC_Displayer.HalconWindow.DispObj(MarkCenterRect.ToRegion());
                                }
                            }
                            catch
                            {

                            }
                        }
						if (this.CreatedShapes.Count > 0)
						{
							//Console.WriteLine("total count: " + CreatedShapes.Count);
							foreach (ShapeNB shape in CreatedShapes)
							{
								shape.Draw(hWC_Displayer.HalconWindow, null, null, windowLen2Image, DisableEdit);
							}
						}
						if (CreatedRegions.Count > 0)
                        {
                            //Console.WriteLine($"region count: {CreatedRegions.Count}");
                            CreatedRegions.ForEach(obj =>
                            {
								if (obj != null)
								{
                                    changeGraphicsContext(obj.GraphicsContext);
                                    if (obj.ShowObject != null && obj.ShowObject.IsInitialized())
										hWC_Displayer.HalconWindow.DispObj(obj.ShowObject);
								}
                            });
						}
                    }
					HSystem.SetSystem("flush_graphic", "true");
                    hWC_Displayer.HalconWindow.DispLine(-100.0, -100.0, -101.0, -101.0);
                }
                catch (Exception ex)
                {
                    //LogHelper.Error("显示", "图像显示异常", ex);
                }
            }
		}
		public void DrawCircle()
		{
			_drawRectangle1 = false;
			_drawCircle = true;
			_drawRectangle2 = false;
			_drawPolygon = false;
			_drawSector = false;
            _drawPoint = false;
            CreatedShapes.ForEach(shape => shape.IsSelected = false);
		}
		public void DrawRectangle1()
		{
			_drawRectangle1 = true;
			_drawCircle = false;
			_drawRectangle2 = false;
			_drawPolygon = false;
			_drawSector = false;
            _drawPoint = false;
            CreatedShapes.ForEach(shape => shape.IsSelected = false);
		}
		public void DrawRectangle2()
		{
			_drawRectangle1 = false;
			_drawCircle = false;
			_drawRectangle2 = true;
			_drawPolygon = false;
			_drawSector = false;
            _drawPoint = false;
            CreatedShapes.ForEach(shape => shape.IsSelected = false);
		}
		public void DrawPolygon()
		{
			_drawRectangle1 = false;
			_drawCircle = false;
			_drawRectangle2 = false;
			_drawPolygon = true;
			_drawSector = false;
            _drawPoint = false;
            CreatedShapes.ForEach(shape => shape.IsSelected = false);
		}
		public void DrawSector()
		{
			_drawRectangle1 = false;
			_drawCircle = false;
			_drawRectangle2 = false;
			_drawPolygon = false;
			_drawSector = true;
            _drawPoint = false;
			CreatedShapes.ForEach(shape => shape.IsSelected = false);
		}
        public void DrawPoint()
        {
            _drawRectangle1 = false;
            _drawCircle = false;
            _drawRectangle2 = false;
            _drawPolygon = false;
            _drawSector = false;
            _drawPoint = true;
            CreatedShapes.ForEach(shape => shape.IsSelected = false);
        }
        public void ClearDisplay()
		{
			ClearAllShapes();
			this.hWC_Displayer.HalconWindow.ClearWindow();
			this.OriginalImage = null;
		}
		public void ClearAllShapes()
		{
			this.CreatedShapes.Clear();
            foreach(DisplayHObjectNB dispObj in CreatedRegions)
            {
                dispObj.Dispose();
            }
			this.CreatedRegions.Clear();
		}
		public void ClearSelectedShape()
		{
			for (int i = 0; i < CreatedShapes.Count; i++)
			{
				if (CreatedShapes[i].IsSelected)
					CreatedShapes.RemoveAt(i);
			}
		}
        public void ClearShapes(string name)
        {
            for(int i = 0; i < CreatedShapes.Count; i++)
            {
                if (CreatedShapes[i].Alias == name)
                    CreatedShapes.Remove(CreatedShapes[i]);
            }
        }
		/// <summary>
		/// 图片适合显示区
		/// </summary>
		public void Fit2Screen()
		{
			OriginX = 0;
			OriginY = 0;
			if (_originalImage != null && _imageWidth > 10 && _imageHeight > 10)
				ZoomFactor = Math.Min(DisplayWidth * 1.0 / _imageWidth, DisplayHeight * 1.0 / _imageHeight);
		}
		public void ResizeDrawingBoard()
        {
			resizeDrawingArea();
			computeDrawingArea();
		}
        public void SetResultTime(string result, Color showColor, double time, string judgeExtra)
        {
            this.BeginInvoke(new Action(() =>
            {
				if (!string.IsNullOrEmpty(judgeExtra))
					this.l_Description.Text = judgeExtra;
				else
				{
					this.l_Description.Text = result;
					this.l_Description.BackColor = showColor;
				}
                this.l_Info.Text = "耗时:" + time.ToString("0.000") + "(s)";
            }));
        }
		public void SetRunInfo(string camName, string vpName)
        {
			this.BeginInvoke( new Action(() =>
			{
				this.l_RunInfo.Visible = true;
				this.l_RunInfo.Text = $"{camName}运行{vpName}";
			}));
        }
		public void HideRunInfo()
        {
			this.BeginInvoke(new Action(() =>
			{
				this.l_RunInfo.Visible = false;
			}));
        }
		public void GenRoiRegion(List<ShapeNB> roiShapes, out HObject roi)
		{
			HObject tmpAdd = null, tmpDiff = null, tmp = null, tmpAddSum = null, tmpDiffSum = null;
			HTuple area, row, col;
			tmpAdd = new HRegion();
			tmpDiff = new HRegion();
			HOperatorSet.GenEmptyRegion(out tmpAdd);
			HOperatorSet.GenEmptyRegion(out tmpDiff);
			tmpAddSum = new HRegion();
			tmpDiffSum = new HRegion();
			HOperatorSet.GenEmptyRegion(out tmpAddSum);
			HOperatorSet.GenEmptyRegion(out tmpDiffSum);
			for (int i = 0; i < roiShapes.Count; i++)
			{
				if (roiShapes[i] is PointNB)
					continue;
				if (roiShapes[i] is TextNB)
					continue;
				if (roiShapes[i] is LineNB)
					continue;
				switch (roiShapes[i].RegOperator)
				{
					case ShapeOperator.Union:
						tmp = roiShapes[i].ToRegion();
						tmpAdd = tmpAddSum;
						if (tmp != null)
							HOperatorSet.Union2(tmp, tmpAdd, out tmpAddSum);
						if (tmpAdd != null)
							tmpAdd.Dispose();
						if (tmp != null)
							tmp.Dispose();
						break;
					case ShapeOperator.Difference:
						tmp = roiShapes[i].ToRegion();
						tmpDiff = tmpDiffSum;
						if (tmp != null)
							HOperatorSet.Union2(tmp, tmpDiff, out tmpDiffSum);
						if (tmpDiff != null)
							tmpDiff.Dispose();
						if (tmp != null)
							tmp.Dispose();
						break;
					default:
						break;
				}
			}

			roi = null;
			HOperatorSet.AreaCenter(tmpAddSum, out area, out row, out col);
			if (area.D > 0)
			{
				HOperatorSet.Difference(tmpAddSum, tmpDiffSum, out tmp);
				HOperatorSet.AreaCenter(tmp, out area, out row, out col);
				if (area.D > 0)
					roi = tmp;
			}
			if (tmpAdd != null)
				tmpAdd.Dispose();
			if (tmpDiff != null)
				tmpDiff.Dispose();
			if (tmpAddSum != null)
				tmpAddSum.Dispose();
			if (tmpDiffSum != null)
				tmpDiffSum.Dispose();
		}
		#endregion

		#region Event
		private void hWC_Displayer_HMouseDown(object sender, HMouseEventArgs e)
		{
			if (!IsAllowMouse)
				return;
            //Console.WriteLine("MouseDown");
			if (_originalImage == null)
				return;
			//图片点
			PointF _currentPoint = new PointF((float)e.X, (float)e.Y);
			PointF _currentWindowPoint = imagePixel2Window(new PointF((float)e.X, (float)e.Y));
			if (e.Button == System.Windows.Forms.MouseButtons.Left)
			{
				if (_drawCircle)
				{
					_drawCircle = false;
					CreatedShapes.Add(new CircleNB() { Center = _currentPoint, IsSelected = true, ChangeModel = PositionNB.Create });
				}
				else if (_drawRectangle1)
				{
					_drawRectangle1 = false;
					CreatedShapes.Add(new Rectangle1NB() { StartPoint = _currentPoint, EndPoint = _currentPoint, IsSelected = true, ChangeModel = PositionNB.Create });
				}
				else if (_drawRectangle2)
				{
					_drawRectangle2 = false;
					CreatedShapes.Add(new Rectangle2NB() { Center = _currentPoint, IsSelected = true, ChangeModel = PositionNB.Create });
				}
				else if (_drawPolygon)
				{
					_drawPolygon = false;
					CreatedShapes.Add(new PolygonNB() { Points = new List<PointF>() { _currentPoint }, IsSelected = true, ChangeModel = PositionNB.Create });
				}
				else if(_drawSector)
				{
					_drawSector = false;
					CreatedShapes.Add(new SectorNB() { Center = _currentPoint, IsSelected = true, ChangeModel = PositionNB.Create });
				}
                else if(_drawPoint)
                {
                    _drawPoint = false;
                    CreatedShapes.Add(new PointNB() { Center = _currentPoint, IsSelected = true, ChangeModel = PositionNB.Create });
                }
                else
				{
					if (!DisableEdit)
					{
						ShapeNB selectedShape = CreatedShapes.FirstOrDefault(shape => shape.PointOnShape(_currentPoint, windowLen2Image) != PositionNB.Out);
						if (selectedShape != null)
						{
							CreatedShapes.ForEach(shape =>
							{
								if (shape.IsSelected)
									shape.IsSelected = false;
							});
							selectedShape.IsSelected = true;
							selectedShape.ChangeModel = selectedShape.PointOnShape(_currentPoint, windowLen2Image);
						}
						else
						{
							CreatedShapes.ForEach(shape => shape.IsSelected = false);
                            //Repaint();
                            _startDrag = true;
						}
					}
                    _dragStartPoint = _currentPoint;
					this.Cursor = Cursors.SizeAll;
				}
			}
			else if (e.Button == System.Windows.Forms.MouseButtons.Right)
			{
                for(int i = 0; i < CreatedShapes.Count; i++)
                {
                    if (CreatedShapes[i].IsSelected)
                    {
                        CreatedShapes[i].IsSelected = false;
                        if (NotifyObserver != null)
                            NotifyObserver(CreatedShapes[i], EVENT_FINISHEDIT_ROI);
                    }
                }
				this.Cursor = Cursors.Default;

                //Console.WriteLine(DateTime.Now.ToString("fff: repaint3"));
				Repaint();
			}
		}
		private void hWC_Displayer_HMouseWheel(object sender, HMouseEventArgs e)
        {
            if (!IsAllowMouse)
                return;
            //lock (this)
            {
                if (e.Delta > 0)
                    ZoomImage(true);
                if (e.Delta < 0)
                    ZoomImage(false);
            }
		}
		private void hWC_Displayer_HMouseMove(object sender, HMouseEventArgs e)
        {
            if (!IsAllowMouse)
                return;
            //Console.WriteLine("MouseMove");

            if (_originalImage == null)
				return;
			PointF _currentPoint = new PointF((float)e.X, (float)e.Y);
			PointF _currentWindowPoint = imagePixel2Window(new PointF((float)e.X, (float)e.Y));
			_zoomPoint = _currentWindowPoint;
			if (_currentPoint.X > 0 && _currentPoint.X < _imageWidth && _currentPoint.Y > 0 && _currentPoint.Y < _imageHeight)
			{
				HTuple color;
                try
                {
                    HOperatorSet.GetGrayval(_originalImage, new HTuple((int)_currentPoint.Y), new HTuple((int)_currentPoint.X), out color);
                    string grayVal = color.Length == 1 ? string.Format(" R,{0} C,{1} | Val:{2} ",
                                                         ((int)_currentPoint.Y).ToString().PadLeft(4, '0'),
                                                         ((int)_currentPoint.X).ToString().PadLeft(4, '0'),
                                                         color.D.ToString().PadLeft(3, '0')) : string.Format(" R,{0} C,{1} | R:{2} G:{3} B:{4} ",
                                                             ((int)_currentPoint.Y).ToString().PadLeft(4, '0'),
                                                             ((int)_currentPoint.X).ToString().PadLeft(4, '0'),
                                                             color.IArr[0].ToString().PadLeft(3, '0'),
                                                             color.IArr[1].ToString().PadLeft(3, '0'),
                                                             color.IArr[2].ToString().PadLeft(3, '0'));

                    if (NotifyGrayVal != null)
                        NotifyGrayVal(grayVal);
                }
                catch(Exception ex)
                {
                    //LogHelper.Error("显示", "显示坐标及灰度异常", ex);
                }
			}
            for(int i = 0; i < CreatedShapes.Count; i++)
            {
                if (CreatedShapes[i].IsSelected)
                {
                    CreatedShapes[i].Change(_currentPoint);
                    Repaint();
                    break;
                }
            }
			if (_startDrag)
			{
				moveImage(_currentPoint);
			}
		}
		bool isOdd = true;
		DateTime t1, t2;
		private void hWC_Displayer_HMouseUp(object sender, HMouseEventArgs e)
		{
            //Console.WriteLine("MouseUp");
			if (e.Button == System.Windows.Forms.MouseButtons.Left)
			{
				if (isOdd)
				{
					t1 = DateTime.Now;
				}
				else
				{
					t2 = DateTime.Now;
				}
				isOdd = !isOdd;
				if (Math.Abs((t1 - t2).TotalMilliseconds) < 300)
				{
					if (OnLeftMouseDoubleClick != null)
						OnLeftMouseDoubleClick();
				}
				_startDrag = false;
				this.Cursor = Cursors.Default;
                //lock (CreatedShapes)
                {
                    for (int i = 0; i < this.CreatedShapes.Count; i++)
                    {
                        if (CreatedShapes[i].IsSelected)
                        {
                            //Console.WriteLine("count: " + CreatedShapes.Count + ",current: " + i);
                            if (CreatedShapes[i].ChangeModel == PositionNB.Create)
                            {
                                CreatedShapes[i].ChangeModel = PositionNB.Out;
                                if (NotifyObserver != null)
                                    NotifyObserver(CreatedShapes[i], EVENT_CREATED_ROI);
                            }
                            else
                            {
                                CreatedShapes[i].ChangeModel = PositionNB.Out;
                                if (NotifyObserver != null)
                                    NotifyObserver(CreatedShapes[i], EVENT_UPDATE_ROI);
                            }
                            //Console.WriteLine(DateTime.Now.ToString("fff: repaint5"));
                            Repaint();
                        }
                    }
                }
			}
		}
        private void hWC_Displayer_MouseEnter(object sender, EventArgs e)
        {
            //if (GetFocus != null)
            //{
            //    GetFocus();
            //}
        }
        public void DrawingBoard_Resize(object sender, EventArgs e)
        {
			resizeDrawingArea();
			Repaint();
        }
        [DllImport("kernel32.dll")]
        public static extern void CopyMemory(long dest, long add, long size);
        public static HObject Bmp2HalconImage(Bitmap image)
        {
            HObject ho_Image = null;
            try
            {
                HOperatorSet.GenEmptyObj(out ho_Image);
                unsafe
                {
                    System.Drawing.Imaging.BitmapData bmpData = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
                    unsafe
                    {
                        HOperatorSet.GenImageInterleaved(out ho_Image, bmpData.Scan0, "bgrx", image.Width, image.Height, -1, "byte", image.Width, image.Height, 0, 0, -1, 0);
                    }
                    image.UnlockBits(bmpData);
                }

            }
            catch
            {
            }
            return ho_Image;
        }
        #endregion
    }
	public class DisplayHObjectNB : IDisposable
	{
		public Dictionary<string, object> GraphicsContext;
		public HObject ShowObject;
		public bool IsText;
		public ShapeNB TextShape;
		public string VisionToolDescription;

		public void Dispose()
		{
			if (ShowObject != null)
				ShowObject.Dispose();
		}
	}
}
